home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-SPAR.{_A / CHECKSUM.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  6KB  |  208 lines

  1. /* $Id: checksum.h,v 1.11 1998/04/17 02:37:22 davem Exp $ */
  2. #ifndef __SPARC64_CHECKSUM_H
  3. #define __SPARC64_CHECKSUM_H
  4.  
  5. /*  checksum.h:  IP/UDP/TCP checksum routines on the V9.
  6.  *
  7.  *  Copyright(C) 1995 Linus Torvalds
  8.  *  Copyright(C) 1995 Miguel de Icaza
  9.  *  Copyright(C) 1996 David S. Miller
  10.  *  Copyright(C) 1996 Eddie C. Dost
  11.  *  Copyright(C) 1997 Jakub Jelinek
  12.  *
  13.  * derived from:
  14.  *    Alpha checksum c-code
  15.  *      ix86 inline assembly
  16.  *      RFC1071 Computing the Internet Checksum
  17.  */
  18.  
  19. #include <asm/uaccess.h> 
  20.  
  21. /* computes the checksum of a memory block at buff, length len,
  22.  * and adds in "sum" (32-bit)
  23.  *
  24.  * returns a 32-bit number suitable for feeding into itself
  25.  * or csum_tcpudp_magic
  26.  *
  27.  * this function must be called with even lengths, except
  28.  * for the last fragment, which may be odd
  29.  *
  30.  * it's best to have buff aligned on a 32-bit boundary
  31.  */
  32. extern unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum);
  33.  
  34. /* the same as csum_partial, but copies from user space while it
  35.  * checksums
  36.  *
  37.  * here even more important to align src and dst on a 32-bit (or even
  38.  * better 64-bit) boundary
  39.  */
  40. /* FIXME: Remove these macros ASAP */
  41. #define csum_partial_copy(src, dst, len, sum) \
  42.             csum_partial_copy_nocheck(src,dst,len,sum)
  43. #define csum_partial_copy_fromuser(s, d, l, w)  \
  44.             csum_partial_copy_from_user((char *) (s), (d), (l), (w), NULL)
  45.  
  46. extern unsigned int csum_partial_copy_sparc64(const char *src, char *dst, int len, unsigned int sum);
  47.             
  48. extern __inline__ unsigned int 
  49. csum_partial_copy_nocheck (const char *src, char *dst, int len, 
  50.                unsigned int sum)
  51. {
  52.     __asm__ __volatile__ ("wr    %%g0, %0, %%asi" : : "i" (ASI_P));
  53.     return csum_partial_copy_sparc64(src, dst, len, sum);
  54. }
  55.  
  56. extern __inline__ unsigned int 
  57. csum_partial_copy_from_user(const char *src, char *dst, int len, 
  58.                 unsigned int sum, int *err)
  59. {
  60.     __asm__ __volatile__ ("wr    %%g0, %0, %%asi
  61.                    stx    %1, [%%sp + 0x7ff + 128]
  62.                   " : : "i" (ASI_S), "r" (err));
  63.     return csum_partial_copy_sparc64(src, dst, len, sum);
  64. }
  65.  
  66. #if 0
  67. /* Not implemented, but nobody uses it yet... */
  68. extern __inline__ unsigned int 
  69. csum_partial_copy_to_user(const char *src, char *dst, int len, 
  70.               unsigned int sum, int *err)
  71. {
  72.     return 0;
  73. }
  74. #endif
  75.   
  76. /* ihl is always 5 or greater, almost always is 5, and iph is word aligned
  77.  * the majority of the time.
  78.  */
  79. extern __inline__ unsigned short ip_fast_csum(__const__ unsigned char *iph,
  80.                           unsigned int ihl)
  81. {
  82.     unsigned short sum;
  83.  
  84.     /* Note: We must read %2 before we touch %0 for the first time,
  85.      *       because GCC can legitimately use the same register for
  86.      *       both operands.
  87.      */
  88.     __asm__ __volatile__("
  89.     sub        %2, 4, %%g7        ! IEU0
  90.     lduw        [%1 + 0x00], %0        ! Load    Group
  91.     lduw        [%1 + 0x04], %%g2    ! Load    Group
  92.     lduw        [%1 + 0x08], %%g3    ! Load    Group
  93.     addcc        %%g2, %0, %0        ! IEU1    1 Load Bubble + Group
  94.     lduw        [%1 + 0x0c], %%g2    ! Load
  95.     addccc        %%g3, %0, %0        ! Sngle    Group no Bubble
  96.     lduw        [%1 + 0x10], %%g3    ! Load    Group
  97.     addccc        %%g2, %0, %0        ! Sngle    Group no Bubble
  98.     addc        %0, %%g0, %0        ! Sngle Group
  99. 1:    addcc        %%g3, %0, %0        ! IEU1    Group no Bubble
  100.     add        %1, 4, %1        ! IEU0
  101.     addccc        %0, %%g0, %0        ! Sngle Group no Bubble
  102.     subcc        %%g7, 1, %%g7        ! IEU1    Group
  103.     be,a,pt        %%icc, 2f        ! CTI
  104.      sll        %0, 16, %%g2        ! IEU0
  105.     lduw        [%1 + 0x10], %%g3    ! Load    Group
  106.     ba,pt        %%xcc, 1b        ! CTI
  107.      nop                    ! IEU0
  108. 2:    addcc        %0, %%g2, %%g2        ! IEU1    Group
  109.     srl        %%g2, 16, %0        ! IEU0    Group regdep    XXX Scheisse!
  110.     addc        %0, %%g0, %0        ! Sngle    Group
  111.     xnor        %%g0, %0, %0        ! IEU0    Group
  112.     srl        %0, 0, %0        ! IEU0    Group        XXX Scheisse!
  113. "    : "=r" (sum), "=&r" (iph)
  114.     : "r" (ihl), "1" (iph)
  115.     : "g2", "g3", "g7", "cc");
  116.     return sum;
  117. }
  118.  
  119. /* Fold a partial checksum without adding pseudo headers. */
  120. extern __inline__ unsigned short csum_fold(unsigned int sum)
  121. {
  122.     unsigned int tmp;
  123.  
  124.     __asm__ __volatile__("
  125.     addcc        %0, %1, %1
  126.     srl        %1, 16, %1
  127.     addc        %1, %%g0, %1
  128.     xnor        %%g0, %1, %0
  129. "    : "=&r" (sum), "=r" (tmp)
  130.     : "0" (sum), "1" (sum<<16)
  131.     : "cc");
  132.     return (sum & 0xffff);
  133. }
  134.  
  135. extern __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
  136.                            unsigned long daddr,
  137.                            unsigned int len,
  138.                            unsigned short proto,
  139.                            unsigned int sum)
  140. {
  141.     __asm__ __volatile__("
  142.     addcc        %1, %0, %0
  143.     addccc        %2, %0, %0
  144.     addccc        %3, %0, %0
  145.     addc        %0, %%g0, %0
  146. "    : "=r" (sum), "=r" (saddr)
  147.     : "r" (daddr), "r" ((proto<<16)+len), "0" (sum), "1" (saddr)
  148.     : "cc");
  149.     return sum;
  150. }
  151.  
  152. /*
  153.  * computes the checksum of the TCP/UDP pseudo-header
  154.  * returns a 16-bit checksum, already complemented
  155.  */
  156. static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
  157.                            unsigned long daddr,
  158.                            unsigned short len,
  159.                            unsigned short proto,
  160.                            unsigned int sum) 
  161. {
  162.     return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
  163. }
  164.  
  165. #define _HAVE_ARCH_IPV6_CSUM
  166.  
  167. static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
  168.                              struct in6_addr *daddr,
  169.                              __u16 len,
  170.                              unsigned short proto,
  171.                              unsigned int sum) 
  172. {
  173.     __asm__ __volatile__ ("
  174.     addcc        %3, %4, %%g7
  175.     addccc        %5, %%g7, %%g7
  176.     lduw        [%2 + 0x0c], %%g2
  177.     lduw        [%2 + 0x08], %%g3
  178.     addccc        %%g2, %%g7, %%g7
  179.     lduw        [%2 + 0x04], %%g2
  180.     addccc        %%g3, %%g7, %%g7
  181.     lduw        [%2 + 0x00], %%g3
  182.     addccc        %%g2, %%g7, %%g7
  183.     lduw        [%1 + 0x0c], %%g2
  184.     addccc        %%g3, %%g7, %%g7
  185.     lduw        [%1 + 0x08], %%g3
  186.     addccc        %%g2, %%g7, %%g7
  187.     lduw        [%1 + 0x04], %%g2
  188.     addccc        %%g3, %%g7, %%g7
  189.     lduw        [%1 + 0x00], %%g3
  190.     addccc        %%g2, %%g7, %%g7
  191.     addccc        %%g3, %%g7, %0
  192.     addc        0, %0, %0
  193. "    : "=&r" (sum)
  194.     : "r" (saddr), "r" (daddr), "r"(htonl((__u32) (len))),
  195.       "r"(htonl(proto)), "r"(sum)
  196.     : "g2", "g3", "g7", "cc");
  197.  
  198.     return csum_fold(sum);
  199. }
  200.  
  201. /* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
  202. extern __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
  203. {
  204.     return csum_fold(csum_partial(buff, len, 0));
  205. }
  206.  
  207. #endif /* !(__SPARC64_CHECKSUM_H) */
  208.